package com.want.client;

import com.want.client.instance.list.ServiceInstanceListService;
import com.want.client.loadbanlance.LoadBalanceSelect;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.web.reactive.function.client.ClientRequest;
import org.springframework.web.reactive.function.client.WebClient;

import java.net.URI;
import java.util.List;

/**
 * @author WangZhiJian
 * @since 2021/12/19 0019
 */
@Slf4j
@Data
public class WantLoadBalanceClient implements Client{

    private Client delegate;

    private String serviceName;

    private LoadBalanceSelect loadBalanceSelect;

    private ServiceInstanceListService serviceInstanceListService;

    public WantLoadBalanceClient(Client delegate, String serviceName, LoadBalanceSelect loadBalanceSelect, ServiceInstanceListService serviceInstanceListService) {
        this.delegate = delegate;
        this.serviceName = serviceName;
        this.loadBalanceSelect = loadBalanceSelect;
        this.serviceInstanceListService = serviceInstanceListService;
    }

    public static WantLoadBalanceClient from(WantLoadBalanceClient client){
        return new WantLoadBalanceClient(client.getDelegate(),null,client.getLoadBalanceSelect(),client.getServiceInstanceListService());
    }

    @Override
    @SneakyThrows
    public WebClient.ResponseSpec exec(ClientRequest request) {
        String url = request.url().toString();
        int i = url.indexOf("/", "http://".length());
        String tempServiceName = null;
        String nextPath = "";
        if(i < 0){
            tempServiceName = url.substring("http://".length());
        }else{
            tempServiceName = url.substring("http://".length(),i);
            nextPath = url.substring(i);
        }
        List<ServiceInstance> serviceInstances = serviceInstanceListService.listServiceInstance(tempServiceName);

        ServiceInstance select = loadBalanceSelect.select(serviceInstances, null);
        String finalUrl = "http://" + select.getHost()+":"+select.getPort()+nextPath;
        log.info("final uri is {}",finalUrl);
        URI uri = new URI(finalUrl);
        return delegate.exec(ClientRequest.from(request).url(uri).build());
    }

}
